package org.autumn.review.thread;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import java.sql.Time;
import java.util.LinkedList;
import java.util.concurrent.TimeUnit;

public class ConsumerAndProducer {
    public static void main(String[] args) {
        MessageQueue messsageQueue = new MessageQueue(2);

        for (int i = 0; i < 3; i++) {
            int id = i;
            Thread t = new Thread(() -> {
                messsageQueue.put(new Message(id, "content:" + id));
            }, "t" + i);
            t.start();
        }


        Thread t1 = new Thread(() -> {
            while (true){
                try {
                    TimeUnit.SECONDS.sleep(1);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                messsageQueue.take();
            }

        }, "t1");
        t1.start();

    }
}

@Slf4j
class MessageQueue {
    private LinkedList<Message> queue = new LinkedList<>();

    private int capacity;

    public MessageQueue(int capacity) {
        this.capacity = capacity;
    }

    public Message take() {
        synchronized (queue) {
            if (queue.isEmpty()) {
                try {
                    log.info("the queue is empty wait ...");
                    queue.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            Message message = queue.removeLast();
            log.info("take message -> {}", message);
            queue.notifyAll();
            return message;
        }
    }


    public void put(Message message) {
        synchronized (queue) {
            if (capacity == queue.size()) {
                try {
                    log.info("the queue is full wait ...");
                    queue.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            queue.addFirst(message);
            log.info("add message -> {}", message);
            queue.notifyAll();
        }
    }
}


@Data
@AllArgsConstructor
class Message {
    private int id;
    private Object val;
}